home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Information / CSMP Digest / volume 1 / csmp-v1-140.txt < prev    next >
Text File  |  1992-12-31  |  45KB  |  1,478 lines

  1. C.S.M.P. Digest             Mon, 13 Jul 92       Volume 1 : Issue 140
  2.  
  3. Today's Topics:
  4.  
  5.     Non-optimized Compiler. Was RE: is System 7 written in c++
  6.     Socket Interface on MacTCP
  7.     How to allocate global for CDEVs?
  8.     Problems with putting a string into a list
  9.     MIDI routines
  10.     Multiple "System Beeps" possible?
  11.     ZREF error?
  12.     PS font name, How to get it from  FOND?!
  13.  
  14.  
  15.  
  16. The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
  17.  
  18. The digest is a collection of article threads from the internet newsgroup
  19. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  20. regularly and want an archive of the discussions.  If you don't know what a
  21. newsgroup is, you probably don't have access to it.  Ask your systems
  22. administrator(s) for details.  (This means you can't post questions to the
  23. digest.)
  24.  
  25. Each issue of the digest contains one or more sets of articles (called
  26. threads), with each set corresponding to a 'discussion' of a particular
  27. subject.  The articles are not edited; all articles included in this digest
  28. are in their original posted form (as received by our news server at
  29. cs.uoregon.edu).  Article threads are not added to the digest until the last
  30. article added to the thread is at least one month old (this is to ensure that
  31. the thread is dead before adding it to the digest).  Article threads that
  32. consist of only one message are generally not included in the digest.
  33.  
  34. The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
  35. [128.223.8.8] in the directory /pub/mac/csmp-digest.  The most recent issues
  36. are available from sumex-aim.stanford.edu [36.44.0.6] in the directory
  37. /info-mac/digest/csmp.  If you don't have ftp capability, the sumex archive
  38. has a mail server; send a message with the text '$MACarch help' (no quotes)
  39. to LISTSERV@ricevm1.rice.edu for more information.
  40.  
  41. These digest is also available via email.  Just send a note saying that you
  42. want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
  43. automatically receive each new issue as it is created.  Sorry, back issues
  44. are not available through the mailing list.
  45.  
  46. Send administrative mail to mkelly@cs.uoregon.edu.
  47.  
  48.  
  49. -------------------------------------------------------
  50.  
  51. From: haceaton@aplcomm.jhuapl.edu (Harry Eaton)
  52. Subject: Non-optimized Compiler. Was RE: is System 7 written in c++
  53. Organization: The Johns Hopkins University Applied Physics Laboratory
  54. Date: Mon, 8 Jun 92 14:33:50 GMT
  55.  
  56. In article <935@6sceng.UUCP> blm@6sceng.UUCP (Brian Matthews) writes:
  57. >... I would say that the System 7 Finder, from
  58. >an assembly point of view, is some of the worst code I've ever seen.  I
  59. >don't know if it's an inherent limitation in C++ or Apple is using a
  60. >horrible compiler, but if you trace through the Finder for a bit, it's
  61. >obvious why the System 7 Finder is so ploddingly slow.
  62.  
  63. This is quite true.  A particularly bad example of code taken from the
  64. system 7 OS (not the finder) follows (note: labels, names etc. are made
  65. up to protect the code's identity :-).  The comments are mine):
  66.  
  67. sub         Link.w  a6,#$0000      ; this compiler links *all* subroutines
  68.             move.l  d7,-(a7)       ; save this register for useless workspace
  69.             move.l  a5,d0          ; save the a5 register in d0
  70.             movea.l (lowglobal),a5 ; load it with a new value
  71.             move.l  d0,d7          ; oops - should have used d7 earlier
  72.             tst.w   theVar(a5)
  73.             ble.s   @1
  74.             move.w  theVar(a5),d0  ; better put this in a register
  75.             subq.w  #1,theVar(a5)  ; oops no register needed
  76. @1          move.l  d7,d0          ; ok - lets go the long way home
  77.             movea.l d0,a5          ; back the way we came!
  78.             move.l  $fffc(a6),d7   ; pop d7 off the stack
  79.             unlk    a6             ; unlink and return
  80.             rts
  81.  
  82. The compiler is clearly far from optimized.  The link instruction is totally
  83. unnecessary for this particular routine; there are no local variables, and
  84. no stack passed arguments.  Saving D7 on the stack is unnecessary because
  85. D7's use is unnecessary.  Saving a5 in d0 would be good except that the
  86. compiler changes its mind right away, and decides to use d7 instead.  The
  87. variable that will be manipulated is needlessly loaded into the d0 register,
  88. and then manipulated directly in memory.  When the old a5 contents are
  89. restored the value follows the quite schizophrenic path from d7 to d0 to a5.
  90. Finally, when d7 is popped from the stack, it is pulled from an offset relative 
  91. to the link.  This has the advantage that the stack can have an
  92. indeterminate number of things left on it and the disadvantage that its slower
  93. and takes more bytes.  In this case, the stack is never indeterminate so the
  94. normal move.l (a7)+,d7 could be used.
  95.  
  96. Some of the above arguments would be false if the routine were ever entered 
  97. from locations other than the top, or if the value of d0 on exit is important.
  98. ease of maintenance and portability.  Presumably the time to market forces and 
  99. competition in software are similar to those in the hardware arena.  Somehow 
  100. the software giants make more $'s than the hardware giants do despite the fact 
  101. that much software today is satisfactory only because of the great leaps in
  102. hardware performance.
  103.  
  104. To end on a good note, the mac ROM code looks pretty decent and fortunately
  105. its still heavily used.
  106.  
  107. Thanks for reading my diatribe
  108. harry eaton
  109. haceaton@aplcomm.jhuapl.edu
  110.  
  111.  
  112.  
  113. +++++++++++++++++++++++++++
  114.  
  115. From: neeri@iis.ethz.ch (Matthias Neeracher)
  116. Date: 9 Jun 92 12:50:01 GMT
  117. Organization: Integrated Systems Laboratory, ETH, Zurich
  118.  
  119. In article <1992Jun8.143350.3311@aplcen.apl.jhu.edu> haceaton@aplcomm.jhuapl.edu (Harry Eaton) writes:
  120. >In article <935@6sceng.UUCP> blm@6sceng.UUCP (Brian Matthews) writes:
  121. >>... I would say that the System 7 Finder, from
  122. >>an assembly point of view, is some of the worst code I've ever seen.
  123. >
  124. >This is quite true.  A particularly bad example of code taken from the
  125. >system 7 OS (not the finder) follows 
  126. >            move.w  theVar(a5),d0  ; better put this in a register
  127. >            subq.w  #1,theVar(a5)  ; oops no register needed
  128. >@1          move.l  d7,d0          ; ok - lets go the long way home
  129.  
  130. This is an annoying habit of apples C compiler: If you write
  131.  
  132. x--;
  133.  
  134. the above code will result, as opposed to if you write
  135.  
  136. - --x;
  137.  
  138. >To end on a good note, the mac ROM code looks pretty decent and fortunately
  139. >its still heavily used.
  140.  
  141. Yes, and this pretty much invalidates the complaints that the performance
  142. problems of Finder et al. are due to sloppy code generation. Wasn't there a
  143. discussion here a while ago that most programs spend the majority of their
  144. time in toolbox calls ?
  145.  
  146. Matthias
  147.  
  148. - -----
  149. Matthias Neeracher                                      neeri@iis.ethz.ch
  150.  `We say "gestalt" when things combine to act in ways we can't explain'
  151.                              -- Marvin Minsky, _The Society Of Mind_
  152.  
  153. +++++++++++++++++++++++++++
  154.  
  155. From: mxmora@unix.SRI.COM (Matt Mora)
  156. Date: 10 Jun 92 02:02:14 GMT
  157. Organization: SRI International, Menlo Park, California
  158.  
  159. In article <NEERI.92Jun9135001@iis.ethz.ch> neeri@iis.ethz.ch (Matthias Neeracher) writes:
  160.  
  161. >Yes, and this pretty much invalidates the complaints that the performance
  162. >problems of Finder et al. are due to sloppy code generation. Wasn't there a
  163. >discussion here a while ago that most programs spend the majority of their
  164. >time in toolbox calls ?
  165.  
  166.  
  167. The people at Apple that are creating the RISC mac's said at the WWDC
  168. that they found most application spend about 80% or more of their time
  169. in the toolbox.  And of the toolbox calls used Drawtext was the most
  170. used and moveto was the runner up. They needed to know which routines
  171. to optimize for RISC that would gain the most benefit. So if they
  172. optimized the critical calls, all applications would see a big
  173. improvement in performance on a RISC machine without any modifications.
  174.  
  175. Matt
  176.  
  177. - -- 
  178. ___________________________________________________________
  179. Matthew Mora                |   my Mac  Matt_Mora@sri.com
  180. SRI International           |  my unix  mxmora@unix.sri.com
  181. ___________________________________________________________
  182.  
  183. ---------------------------
  184.  
  185. From: ldh@svl.cdc.com (Lawrence Hare)
  186. Subject: Socket Interface on MacTCP
  187. Date: 8 Jun 92 17:25:05 GMT
  188. Organization: Control Data Corporation, Silicon Valley Operations
  189.  
  190. I am attempting to locate a socket interface library compliant with
  191. BSD 4.3 for use with MacTCP. This will permit crossplatform code
  192. at the network level (Mac & PC). NOVELL used to have one but it
  193. is no longer on the market. I am told that there are some public
  194. domain offerings available - but I know not where.
  195.  
  196. If anyone can tell me where I may obtain such a library, I would
  197. be very grateful.
  198.  
  199.  
  200. +++++++++++++++++++++++++++
  201.  
  202. From: hardin@dino.cad.mcc.com (John Hardin)
  203. Date: 9 Jun 92 23:55:03 GMT
  204. Organization: MCC CAD Program, Austin, Texas
  205.  
  206. Lawrence Hare (ldh@svl.cdc.com) writes:
  207. >  
  208. >  I am attempting to locate a socket interface library compliant with
  209. >  BSD 4.3 for use with MacTCP. This will permit crossplatform code
  210. >  at the network level (Mac & PC). NOVELL used to have one but it
  211. >  is no longer on the market. I am told that there are some public
  212. >  domain offerings available - but I know not where.
  213. >  
  214. >  If anyone can tell me where I may obtain such a library, I would
  215. >  be very grateful.
  216.  
  217. The folks at MIT have written this VERY thing!  (However, I can't
  218. vouch for it's BSD 4.3 compliance, though.)  I ftp'd it from
  219. net-dist.mit.edu (18.72.0.3).  If I remember correctly, it's part of
  220. the TechMail-2.0 release.  It was originally written for MPW (3.1?)
  221. and MacTCP 1.0, but I have subsequently ported it to ThinkC 4.0/5.0
  222. (running on MacTCP 1.1).  I've also fixed some bugs.  I haven't
  223. finished ALL of my testing, but as soon as I do, I'll return the code
  224. to MIT (given they want it).
  225.  
  226. - -jwh
  227. - --
  228. John W. Hardin            phone:  (512)338-3535
  229. MCC                email:  hardin@mcc.com
  230. 3500 W. Balcones Center Dr  fax:    (512)338-3897
  231. Austin, TX  78759-6509        uucp:   ...!cs.utexas.edu!milano!cadillac!hardin
  232.  
  233. ---------------------------
  234.  
  235. From: mmoss@engws5.ic.sunysb.edu (Matthew D Moss)
  236. Subject: How to allocate global for CDEVs?
  237. Organization: State University of New York at Stony Brook
  238. Date: Mon, 8 Jun 1992 18:35:43 GMT
  239.  
  240.  
  241. I am writing a Control Panel Device using the method described in THINK C
  242. 4.0's class library. I need to use modal dialogs, however, the standard
  243. calls to read the dialog from the resource and enter the modal dialog
  244. don't do anything.
  245.  
  246. As I guess, this is due to the fact that CDEV's cannot have global variables.
  247. How can I get around this? (I don't have IM).
  248.  
  249. Thanx in advance.
  250. - -- 
  251. - -------------------------------------------------------------------------------
  252. Matthew David Moss                mmoss@ic.sunysb.edu
  253.     "Artificial intelligence is no        mmoss@ccmail.sunysb.edu
  254.      match for natural stupidity."
  255.  
  256. +++++++++++++++++++++++++++
  257.  
  258. From: keith@taligent.com (Keith Rollin)
  259. Date: 9 Jun 92 18:11:32 GMT
  260. Organization: Taligent
  261.  
  262. In article <1992Jun8.183543.1098@sbcs.sunysb.edu>, mmoss@engws5.ic.sunysb.edu
  263. (Matthew D Moss) writes:
  264. > I am writing a Control Panel Device using the method described in THINK C
  265. > 4.0's class library. I need to use modal dialogs, however, the standard
  266. > calls to read the dialog from the resource and enter the modal dialog
  267. > don't do anything.
  268. > As I guess, this is due to the fact that CDEV's cannot have global variables.
  269. > How can I get around this? (I don't have IM).
  270.  
  271. I'm afraid your guess is incorrect. The problem is not due to CDEV's not being
  272. able to use global variables. The Dialog Manager routines don't depend on the
  273. existence or non-existence of an application's globals (other than a valid A5
  274. world with QD globals, which any CDEV will have).
  275.  
  276. (BTW: CDEV's _can_ use global variables. THINK users can use the A4 routines,
  277. and MPW users can use the technique in Technote #256.)
  278.  
  279. Your problem probably lies elsewhere, like in the formation of your DLOG or
  280. DITL. It's possible, for example, that your dialog is being created at a
  281. location way off your screen, or that its size is 0, 0. I've never experienced
  282. your problem, so without more details, I couldn't suggest any more reasons for
  283. the problem.
  284.  
  285. - --
  286. Keith Rollin
  287. Phantom Programmer
  288. Taligent, Inc.
  289.  
  290. ---------------------------
  291.  
  292. From: marshall@kauri.vuw.ac.nz (Stephen Marshall)
  293. Subject: Problems with putting a string into a list
  294. Date: 8 Jun 92 23:33:30 GMT
  295. Organization: Victoria University of Wellington
  296.  
  297. Hi, I'm having trouble feeding a string into a list cell, the string
  298. looks fine when I check it with lightsbug, but when it is displayed 
  299. on the list, it gets cut off at the end, and uaually gets an extra
  300. character (square box) at front, increasing the length of the data 
  301. put into the list by one gets the end right, but why should that be
  302. necessary, and why does the other rubbish end up in front?
  303.  
  304. Any help apprecieated, Stephen
  305.  
  306. (code follows:)
  307.     temp := LAddRow(1, (counter - 1), theListHandle);
  308.     SetPt(cSize, 0, (counter - 1));
  309. {extract the data from the ProcessInfoRec}
  310.     theError := GetProcessInformation(myPSNList.element[counter], theProcessInfo);
  311.  
  312.     theString := theProcessInfo.processName^;
  313.  
  314. {Insert the data into the list}
  315.     LSetCell(@theString, (Length(theString) + 1), cSize, theListHandle);
  316.  
  317. Thanks again, Stephen
  318.  
  319. +++++++++++++++++++++++++++
  320.  
  321. From: mxmora@unix.SRI.COM (Matt Mora)
  322. Date: 10 Jun 92 01:50:38 GMT
  323. Organization: SRI International, Menlo Park, California
  324.  
  325. In article <1992Jun8.233330.7161@rata.vuw.ac.nz> marshall@kauri.vuw.ac.nz (Stephen Marshall) writes:
  326.  
  327. The problem is that you are storing the length byte with the data. If you
  328. write your own LDEF you can deal with it yourself otherwise
  329. you need to strip it out before you insert it in to the list and
  330. put it back when you get the data out. (if you do)
  331.  
  332. Try:
  333.  
  334. >{Insert the data into the list}
  335. >    LSetCell(@theString, (Length(theString) + 1), cSize, theListHandle);
  336.  
  337.      LSetCell(Ptr(Ord(@theString)+1),Length(thestring),cSize, theListHandle);
  338.  
  339.  
  340. Now when you want the string back:
  341.      datalen:=255;
  342.      LGetCell(Ptr(Ord(@theString)+1),datalen,theCell,theListHandle);
  343.      theString[0]:=chr(datalen);  { compiler might complain about array bounds}
  344.  
  345.  
  346. Matt
  347.  
  348. - -- 
  349. ___________________________________________________________
  350. Matthew Mora                |   my Mac  Matt_Mora@sri.com
  351. SRI International           |  my unix  mxmora@unix.sri.com
  352. ___________________________________________________________
  353.  
  354. ---------------------------
  355.  
  356. Organization: Junior, Math/Computer Science, Carnegie Mellon, Pittsburgh, PA
  357. Date: Tue,  9 Jun 1992 12:16:30 -0400 
  358. From: Lian-Keng Lim <ll1n+@andrew.cmu.edu>
  359. Subject: MIDI routines
  360.  
  361. Hello,
  362. I am looking for some MIDI routines for an application that I am writing
  363. in Think C.  Can anyone point me in the right direction as to where I
  364. can source these codes?
  365.  
  366. I would also appreciate the following information if anyone can supply them...
  367.  
  368. 1. what is opcode MIDI intrepeter? if it means anything at all...
  369. 2. are there C codes for MIDIPascal routines by AlTech Systems? If so,
  370. how can I get them.
  371. 3.where and how can I get a copy of Mac Software Catalog?
  372.  
  373. Thanks a bunch in advance for all information.
  374.  
  375. Peace,
  376. Keng.
  377.  
  378. +++++++++++++++++++++++++++
  379.  
  380. From: steve@oceania.com (Steve Dakin)
  381. Date: 9 Jun 92 20:04:53 GMT
  382. Organization: Oceania Health Care Systems
  383.  
  384. In article <8eBBZS200iUyA2zHMW@andrew.cmu.edu>  writes:
  385.  
  386. > 2. are there C codes for MIDIPascal routines by AlTech Systems? If so,
  387. > how can I get them.
  388.  
  389. According to Altech's product information, the MidiPascal routines require  
  390. "Lightspeed Pascal, Lightspeed C, or TurboPacal."  Also, the girl I spoke with  
  391. at Altech said they are compatible with THINK C 5.0.
  392.  
  393. You might also want to try Apple's MIDI Management Tools Set.  I used this in a  
  394. MIDI program I wrote and it worked quite well.  It's less expensive (that's a  
  395. first) at $35 vs. $100 for Altech's routines.  However, if you plan to sell or  
  396. distribute anything you write, Apple requires a $100 licensing fee per product  
  397. per year and Altech's is free of licensing fees.
  398.  
  399. Altech's number is 318-868-8036
  400. APDA's number is 800-282-2732
  401.  
  402. Don't expect to receive any technical information from either number.
  403.  
  404. - -Steve
  405. - -- 
  406.     Steve Dakin                      Oceania Health Care Systems 
  407.  steve@oceania.com (NeXT mail)       Palo Alto, CA (415) 322-0127
  408.  jester@oceania.com                  "That one deserves a ... WOW!"
  409.  
  410. ---------------------------
  411.  
  412. From: dvb@squid.inmet (David V. Baker)
  413. Subject: Multiple "System Beeps" possible?
  414. Date: 9 Jun 92 17:01:58 GMT
  415. Organization: Intermetrics, Inc. (Ada Division)
  416.  
  417.  
  418. *I'm looking to have different beeps for different applications.*
  419.  
  420.  
  421. Does anyone "out there" know if (and how) I can have multiple "beeps"
  422. on my machine?  Specifically, I would like MacX (and therefore my
  423. terminal windows) to have a different beep-sound than the rest of my
  424. machine.  Is there some magic id number I could paste a sound into MacX
  425. and bypass the request to the System for the standard beep?  Could an
  426. INIT of some sort force an override of the beep sound?
  427.  
  428. I don't mind hacking up a copy of MacX (or any other application), if I
  429. know where to look.
  430.  
  431. If you can answer, thanks for the smarts.
  432. dvb
  433. - --
  434. - -------------------------------------------------------------------
  435. David V. Baker
  436. Intermetrics, Inc.               dvb@inmet.camb.inmet.com
  437. Cambridge, MA 02138                (617) 661-1840x4644
  438.  
  439. +++++++++++++++++++++++++++
  440.  
  441. From: aconn@jade.tufts.edu (Zoom Master 1                                     )
  442. Date: 9 Jun 92 19:03:16 GMT
  443. Organization: Tufts University - Medford, MA
  444.  
  445.  
  446. Use the GREAT shareware program Speed Beep. Get version 2.0.6.
  447.  
  448. +++++++++++++++++++++++++++
  449.  
  450. From: barrett@ial4.jsc.nasa.gov (Jim Barrett)
  451. Date: 9 Jun 92 20:31:52 GMT
  452. Organization: Lockheed Engineering & Sciences Co.
  453.  
  454. In article <DVB.92Jun9130158@squid.inmet>, dvb@squid.inmet (David V. Baker) writes:
  455. > *I'm looking to have different beeps for different applications.*
  456. > Does anyone "out there" know if (and how) I can have multiple "beeps"
  457. > on my machine?  Specifically, I would like MacX (and therefore my
  458. > terminal windows) to have a different beep-sound than the rest of my
  459. > machine.  Is there some magic id number I could paste a sound into MacX
  460. > and bypass the request to the System for the standard beep?  Could an
  461. > INIT of some sort force an override of the beep sound?
  462.  
  463. I don't know of an INIT, but I know how to do this with ResEdit.  
  464.  
  465. WARNING - the following is more that I know about the Macintosh.  I learned 
  466. this trick from a Mac developer friend.  
  467.  
  468. Apparently, when the system opens any resource, it searches the current 
  469. application, and then it searches the system.  If you had selected SND id 256,
  470. for instance, and your software generates a beep, the system searches your
  471. open application for sound resource id 256, and then it searches the system
  472. itself, which is where it typically finds the sound.  However, if you set your
  473. system beep to whatever sound is associated with, say, 256, and there just 
  474. happens to be a sound id 256 in your current application, the one in your 
  475. application will sound when your app ic current, and the one in the system
  476. suitcase will sound for other apps.  
  477.  
  478. What I've done:  I resedited my system suitcase (make a backup first, ok?), 
  479. and created a sound resource of ID 256, and gave it a name like "sound #256". 
  480. Then I open the sound control panel and make "sound #256" the system beep.  
  481. Finally, I resedit my application (make another backup first, ok?), and copy 
  482. in a sound resource, and give it a resource id of 256.  voila!  My telnet 
  483. application has a nice short beep, and my other applications have a longer, 
  484. more entertaining beep.  
  485.  
  486. If anyone has a better idea, I'm sure they'll post ... :-)  
  487.  
  488. Regards,
  489. Jim
  490.  
  491. ---------------------------
  492.  
  493. From: jstevens@crick.ssctr.bcm.tmc.edu (Jason Philip Stevens)
  494. Subject: ZREF error?
  495. Date: 9 Jun 92 22:31:50 GMT
  496. Organization: Baylor College of Medicine, Houston, Tx
  497.  
  498.  
  499. I'm writing an application with TCL 1.1 and Think C 5.0.  I keep getting "ZREF" errors that ask me to remove objects and re-make my code.  This is a painfully
  500. time-consuming process;  does anyone have any idea what causes these errors and
  501. what I can do to prevent them?
  502.  
  503. - -jps
  504.  
  505. PS: Frequent = ~3 times/day, code size is about 106,000 lines, on a mac II with
  506. sys 7.0 (no tuneup) and 5 mb ram.
  507.  
  508.  
  509.  
  510.  
  511. - -- 
  512. Jason Stevens            Internet:  jstevens@bcm.tmc.edu
  513. Network User Services        Voice:  (713) 798-7370
  514. Baylor College of Medicine    Opinions expressed are mine alone.
  515.  
  516. +++++++++++++++++++++++++++
  517.  
  518. From: mspace@netcom.com (Brian Hall)
  519. Date: Tue, 09 Jun 92 23:32:52 GMT
  520. Organization: Netcom - Online Communication Services  (408 241-9760 guest) 
  521.  
  522. jstevens@crick.ssctr.bcm.tmc.edu (Jason Philip Stevens) writes:
  523. >I'm writing an application with TCL 1.1 and Think C 5.0.  I keep getting "ZREF" errors that ask me to remove objects and re-make my code.  This is a painfully
  524. >time-consuming process;  does anyone have any idea what causes these errors and
  525. >what I can do to prevent them?
  526.  
  527. >-jps
  528.  
  529. >PS: Frequent = ~3 times/day, code size is about 106,000 lines, on a mac II with
  530. >sys 7.0 (no tuneup) and 5 mb ram.
  531.  
  532. I had the same problem working on a IIfx 20/210.  My project contained
  533. about 40 subprojects and around 200 source files.  Even though ThC claims
  534. to use multifinder temp mem, meaning you should not have to increase
  535. the partition size, I found the only way to reliably exorcise the ZREF
  536. error was to increase the compilers partition by a large amount (I made
  537. it 4M for that particular app, and 2M for a smaller app I am doing on a
  538. IIsi).
  539.  
  540. My other beef with 5.0 is that it *still* uses the resource manager for
  541. the project file.  This can get *real* slow with a large project.  Just
  542. the time it takes to remove and then add resources during a compile can
  543. become significant.  A little trick I use is to do a remove objects if
  544. a significant number of files will need to be recompiled.  This is faster
  545. because you are just doing address instead of a bunch of changedres calls.
  546.  
  547.  
  548. - -- 
  549.  
  550.  \ | /   | Brian Hall                 mspace@netcom.com
  551.  - : -   | Mark/Space Softworks       Applelink: markspace
  552.   /|\    |                            America Online: MarkSpace
  553.  |-+-|   |
  554. /-\|/-\  | People don't kill people, toasters kill people.
  555.  
  556. ---------------------------
  557.  
  558. From: de19@umail.umd.edu (Dana S Emery)
  559. Subject: PS font name, How to get it from  FOND?!
  560. Date: 10 Jun 92 06:59:59 GMT
  561. Organization: Personal
  562.  
  563. In article <13798@umd5.umd.edu>, de19@umail.umd.edu (Dana S Emery) writes:
  564. > In article <14271@ucdavis.ucdavis.edu>, lim@iris.ucdavis.edu (Lloyd Lim) writes:
  565. > > 
  566. > > In article <10s9ocINNdd2@agate.berkeley.edu> ewylie@ocf.berkeley.edu (Elizabeth Wylie) writes:
  567. > > >
  568. > > >I am trying to determine whether a particular font (given a font name and
  569. > > >number) has a PostScript counterpart that will be handled by ATM. I've
  570. > > >been told that ATM has some callback routines that would help me out,
  571. > > >but I don't know what these routines are.
  572. > > >
  573. > > Yes, the procedure is named fontAvailableATM.  It's not hard but it's
  574. > > a bit long to describe here.
  575. > Suitcase is able to access some field in the FOND which defines the
  576. > PS font name (ie TimesRomBol), so ATM shouldnt be necesary (unless one
  577. > also needed to confirm the existance of the related 'LWFN').  I vaguely
  578. > remember some doc on this, but cant place it just now.
  579. > DSE (de19@umail.umd.edu)
  580.  
  581. in <1992Jun9.184919.22275@reed.edu>, orpheus@reed.edu (P. Hawthorne)
  582.  
  583. went on at length re: ATM backdoor solution, which is ok, but leaves
  584. my (de19) question unanswered.
  585.  
  586.         - Suitcase gets the PS file name from inspection of the FOND/FONT/NFNT/..
  587.   - what is it looking at?
  588.  
  589. My question is more than idle, as I have dreams of writing a font editor
  590. some day.
  591.  
  592. Dana S Emery (de19@umail.umd.edu)
  593.  
  594.  
  595.  
  596. +++++++++++++++++++++++++++
  597.  
  598. From: orpheus@reed.edu (P. Hawthorne)
  599. Date: 11 Jun 92 00:50:56 GMT
  600. Organization: Reed College, Portland, Oregon
  601.  
  602.  
  603.   ewylie@ocf.berkeley.edu (Elizabeth Wylie) inquires:
  604. . I am trying to determine whether a particular font (given a font name and
  605. . number) has a PostScript counterpart that will be handled by ATM. I've been
  606. . told that ATM has some callback routines that would help me out, but I
  607. . don't know what these routines are.
  608.  
  609.   orpheus@reed.edu (Prometheus Hawthorne) replies:
  610. . The package is available for anonymous ftp on sumex-aim.stanford.edu. 
  611. . Adobe assumes you are using Think C and they have been unable to come 
  612. . up with a backdoor interface for other compilers. Just in case, here is my
  613. . code for using ATM with Think Pascal. 
  614.  
  615.  [Meanwhile, on another typographical tangent...]
  616.  
  617.   de19@umail.umd.edu (Dana S Emery) writes:
  618. . Suitcase is able to access some field in the FOND which defines the
  619. . PS font name (ie TimesRomBol), so ATM shouldnt be necesary (unless one
  620. . also needed to confirm the existance of the related 'LWFN').  I vaguely
  621. . remember some doc on this, but cant place it just now.
  622.  
  623.   orpheus@reed.edu (P. Hawthorne) defers:
  624. . The best documentation for this (as well as the most lucid, descriptive and
  625. . salient discussion of the FOND resource) is available from Adobe Developer 
  626. . Technical Support. 
  627.  
  628.   de19@umail.umd.edu (Dana S Emery) writes:
  629. .  - Suitcase gets the PS file name from inspection of the FOND/FONT/NFNT/
  630. .  - What is it looking at?
  631.  
  632.   I am hoping not to have to explain the FOND mechanism itself, since it
  633. is an involved exercise in parsing and sorting that is best described
  634. by the Adobe documentation. That being said, at least post my source code
  635. for doing it, and I can give you an overview of what is involved.
  636.  
  637.   In QuickDraw, a typeface is available to you by number, and resource
  638. name.  Neither system is any good for typographical purposes. Look at
  639. Adobe Illustrator for an example of good font picking. The PostScript names
  640. are superior.
  641.  
  642.   If you step through every typeface by QuickDraw resource number,  just
  643. like TextFont, you can get the base PostScript typeface name. Maybe
  644. just for thrills you would use a heap for this with a priority function
  645. on the resource name.  If you step through every style by QuickDraw style
  646. index, just like TextFace, you can get a bunch of suffixes to attach to
  647. your base font name.
  648.  
  649.   Then you have a mapping between what PostScript type face and style you 
  650. want to use and what QuickDraw numbers you have to use in order to generate 
  651. that face and style on the Macintosh screen.
  652.  
  653.   As for the arcane nitty gritty, mostly offsets from indices into
  654. offsets from the resource handle, this is what the FOND documentation
  655. from Adobe is for.  Using it, I was able to replace that agonizingly long
  656. typeface menu with a series of menus for type family, face and style.
  657. There are some intricacies involved, but if you can parse out the Futura
  658. family youUre doing fine. (Oh yeah, watch out for Futura Condensed.)
  659.  
  660.   Here is as far as I got with doing this trick, right after getting
  661. Think Pascal and working my way through the toolbox. No fair
  662. criticizing the style, cuz I was just barely getting used to using Pascal
  663. instead of C and was just reverse engineering the whole thing before I
  664. got the documentation. I think there's a bug in the QuickSort. Apologies
  665. made, here it is.
  666.  
  667.   Theus (orpheus@reed.edu) "Man, these self-inflicted caffeine
  668.                 deprivation headaches suck..."
  669.  
  670. - ---------- Cut here
  671.  
  672.  Type
  673.   FondRecord = Record
  674.     FlagWord: Integer;
  675.     FamilyID: Integer;
  676.     FirstChar: Integer;
  677.     LastChar: Integer;
  678.     Ascent: Integer;
  679.     Descent: Integer;
  680.     Leading: Integer;
  681.     WidMax: Integer;
  682.     WidOff: Longint;
  683.     KernOff: Longint;
  684.     StyleMapOff: Longint;
  685.    End;
  686.  
  687.   StyleMappingTable = Record
  688.     FontClass: Integer;
  689.     EncodeOff, Reserved: Longint;
  690.     StyleIndex: Packed Array[0..47] Of Byte;
  691.     NumStyles: Integer;
  692.     BaseFont: Str255;
  693.    End;
  694.  
  695.   FontRecord = Record
  696.     PSFamily: String[64];
  697.     PSFace: String[64];
  698.     PSStyle: String[64];
  699.     QDFont: String[64];
  700.     QDFace: Integer;
  701.     QDStyle: Style;
  702.    End;
  703.  
  704.   FontSpec = Record
  705.     QDFace: Integer;
  706.     QDStyle: Style;
  707.     QDSize: Integer;
  708.    End;
  709.  
  710.   Typographer = Object(Abstract)
  711.     Count: Integer;
  712.     Fonds: Integer;
  713.     Fonts: Array[0..maxFonts] Of FontRecord;
  714.  
  715.     Procedure Typographer.Construct;
  716.     Procedure Typographer.Destruct;
  717.     Procedure Typographer.Update;
  718.  
  719.     Procedure Typographer.Expect (aLongint: Longint);
  720.     Procedure Typographer.Insert (aFont: FontRecord);
  721.  
  722.     Function Typographer.GetEntry (anIndex: Integer): FontRecord;
  723.     Procedure Typographer.SetEntry (anIndex: Integer; aFont: FontRecord);
  724.  
  725.     Procedure Typographer.SetMenu (aMenu: MenuHandle; aContents: Integer;
  726. aFamily, aFace: Str255);
  727.  
  728.     Function Typographer.GetDefaultFace (aPSFamily: Str255): Str255;
  729.     Function Typographer.GetDefaultStyle (aPSFamily, aPSFace: Str255): Str255;
  730.  
  731.     Function Typographer.GetFontSpec (aPSFamily, aPSFace, aPSStyle: Str255;
  732. aSize: Extended): FontSpec;
  733.  
  734.     Procedure Typographer.Develop;
  735.     Procedure Typographer.Sort;
  736.     Procedure Typographer.Unique;
  737.     Procedure Typographer.Harmony;
  738.    End;
  739.  
  740.  Const
  741.   fontRecordSize = Longint(SizeOf(FontRecord));
  742.  
  743.  Var
  744.   theTypographer: Typographer;
  745.  
  746.  Procedure Typographer.Construct;
  747.  Begin
  748.  Lock;
  749.  Count := -1;
  750.  Fonds := 0;
  751.  End;
  752.  
  753.  Procedure Typographer.Update;
  754.  Begin
  755.  If CountResources('FOND') <> Fonds Then
  756.   Begin
  757.   Count := 0;
  758.   Develop;
  759.   End;
  760.  End;
  761.  
  762.  Procedure Typographer.Expect (aLongint: Longint);
  763.  Begin
  764.  aLongint := 6 + (aLongint + 1) * fontRecordSize;
  765.  Ignore(Grow(aLongint));
  766.  End;
  767.  
  768.  Procedure Typographer.Insert (aFont: FontRecord);
  769.   Var
  770.    aPtr: Ptr;
  771.  Begin
  772.  Expect(Count + 3);
  773.  Count := Count + 1;
  774.  SetEntry(Count, aFont);
  775.  End;
  776.  
  777.  Function Typographer.GetEntry (anIndex: Integer): FontRecord;
  778.   Var
  779.    aPtr: Ptr;
  780.    aFont: FontRecord;
  781.  Begin
  782.  aPtr := Ptr(Longint(@Fonts) + fontRecordSize * anIndex);
  783.  BlockMove(aPtr, @aFont, fontRecordSize);
  784.  GetEntry := aFont;
  785.  End;
  786.  
  787.  Procedure Typographer.SetEntry (anIndex: Integer; aFont: FontRecord);
  788.   Var
  789.    a, i, o: Ptr;
  790.    e, u: Longint;
  791.    aPtr: Ptr;
  792.  Begin
  793.  aPtr := Ptr(Longint(@Fonts) + fontRecordSize * anIndex);
  794.  a := @Self;
  795.  e := HandleSize(Self);
  796.  i := Ptr(Longint(a) + Longint(e));
  797.  o := @Fonts;
  798.  u := fontRecordSize * anIndex;
  799.  If (Longint(aPtr) < Longint(o)) Then
  800.   Danger('The typeface Typographer attempted to thrash low memory.')
  801.  Else If (Longint(aPtr) > Longint(e)) Then
  802.   Danger('The typeface Typographer attempted to thrash high memory.');
  803.  BlockMove(@aFont, aPtr, fontRecordSize);
  804.  End;
  805.  
  806.  Function Typographer.GetFontSpec (aPSFamily, aPSFace, aPSStyle: Str255;
  807. aSize: Extended): FontSpec;
  808.   Var
  809.    a, e: Integer;
  810.    aFont: FontRecord;
  811.    found: Boolean;
  812.  Begin
  813.  GetFontSpec.QDFace := 0;
  814.  GetFontSpec.QDStyle := [];
  815.  GetFontSpec.QDSize := Trunc(aSize);
  816.  
  817.  found := false;
  818.  For a := 0 To Count Do
  819.   Begin
  820.   aFont := GetEntry(a);
  821.   If (aFont.PSFamily = aPSFamily) And (aFont.PSFace = aPSFace) And
  822. (aFont.PSStyle = aPSStyle) Then
  823.    Begin
  824.    found := true;
  825.    GetFontSpec.QDFace := aFont.QDFace;
  826.    GetFontSpec.QDStyle := aFont.QDStyle;
  827.    a := Count;
  828.    End;
  829.   End;
  830.  
  831.  If Not found Then
  832.   Notice('Could not get a font specification with PostScript identifiers.');
  833.  End;
  834.  
  835.  Function Typographer.GetDefaultFace (aPSFamily: Str255): Str255;
  836.   Var
  837.    a, e: Integer;
  838.    aFont: FontRecord;
  839.    found, gotten: Boolean;
  840.  Begin
  841.  found := false;
  842.  
  843.  GetDefaultFace := 'Regular';
  844.  For a := 0 To Count Do
  845.   Begin
  846.   aFont := GetEntry(a);
  847.   If (aFont.PSFamily = aPSFamily) Then
  848.    If (aFont.QDStyle = []) Then
  849.     Begin
  850.     If (aFont.PSFace = 'Regular') Or (aFont.PSFace = 'Medium') Then
  851.      Begin
  852.      found := true;
  853.      GetDefaultFace := aFont.PSFace;
  854.      End;
  855.     End
  856.    Else If found Then
  857.     a := Count
  858.   End;
  859.  
  860.  End;
  861.  
  862.  Function Typographer.GetDefaultStyle (aPSFamily, aPSFace: Str255): Str255;
  863.   Var
  864.    a, e: Integer;
  865.    aFont: FontRecord;
  866.    found, gotten: Boolean;
  867.  Begin
  868.  found := false;
  869.  gotten := false;
  870.  GetDefaultStyle := 'Regular';
  871.  For a := 0 To Count Do
  872.   Begin
  873.   aFont := GetEntry(a);
  874.   If (aFont.PSFamily = aPSFamily) And (aFont.PSFace = aPSFace) Then
  875.    Begin
  876.    found := true;
  877.    If (aFont.QDStyle = []) Then
  878.     If Not gotten Then
  879.      Begin
  880.      Begin
  881.      GetDefaultStyle := aFont.PSStyle;
  882.      gotten := true;
  883.      End;
  884.      End
  885.     Else If (aFont.PSStyle = 'Roman') Or (aFont.PSStyle = 'Regular') Or
  886. (aFont.PSStyle = 'Book') Or (aFont.PSStyle = 'Medium') Then
  887.      Begin
  888.      GetDefaultStyle := aFont.PSStyle;
  889.      End;
  890.    End
  891.   Else If gotten Then
  892.    a := Count
  893.   Else If found Then
  894.    Begin
  895.    Caution('Problem finding default style.');
  896.    a := Count;
  897.    End;
  898.   End;
  899.  End;
  900.  
  901.  Procedure Typographer.SetMenu (aMenu: MenuHandle; aContents: Integer;
  902. aFamily, aFace: Str255);
  903.   Var
  904.    a, e, i: Integer;
  905.    aFont: FontRecord;
  906.    previousFamily, previousFace, previousStyle: Str255;
  907.  Begin
  908.  UnlockHandle(aMenu);
  909.  a := CountMItems(aMenu);
  910.  For e := a Downto 1 Do
  911.   DelMenuItem(aMenu, e);
  912.  
  913.  Case aContents Of
  914.  familyMenu: 
  915.   Begin
  916.   previousFamily := '';
  917.   e := 0;
  918.   For a := 0 To Count Do
  919.    Begin
  920.    aFont := GetEntry(a);
  921.    If aFont.PSFamily <> previousFamily Then
  922.     Begin
  923.     InsMenuItem(aMenu, aFont.PSFamily, e);
  924.     e := e + 1;
  925.     previousFamily := aFont.PSFamily;
  926.     i := CountMItems(aMenu);
  927.     End;
  928.    End;
  929.   End;
  930.  
  931.  faceMenu: 
  932.   Begin
  933.   previousFace := '';
  934.   e := 0;
  935.   For a := 0 To Count Do
  936.    Begin
  937.    aFont := GetEntry(a);
  938.    If (aFont.PSFamily = aFamily) Then
  939.     If (aFont.PSFace <> previousFace) Then
  940.      Begin
  941.      InsMenuItem(aMenu, aFont.PSFace, e);
  942.      e := e + 1;
  943.      previousFace := aFont.PSFace;
  944.      i := CountMItems(aMenu);
  945.      End;
  946.    End;
  947.   End;
  948.  
  949.  styleMenu: 
  950.   Begin
  951.   previousStyle := '';
  952.   e := 0;
  953.   For a := 0 To Count Do
  954.    Begin
  955.    aFont := GetEntry(a);
  956.    If (aFont.PSFamily = aFamily) Then
  957.     If (aFont.PSFace = aFace) Then
  958.      If aFont.PSStyle <> previousStyle Then
  959.       Begin
  960.       InsMenuItem(aMenu, aFont.PSStyle, e);
  961.       e := e + 1;
  962.       previousStyle := aFont.PSStyle;
  963.       i := CountMItems(aMenu);
  964.       End
  965.      Else If e > 0 Then
  966.       a := Count;
  967.    End;
  968.   End;
  969.  
  970.  Otherwise
  971.   Caution('Tried to fill a typeface-related menu with unknown items.');
  972.  End;
  973.  LockHandle(aMenu);
  974.  End;
  975.  
  976.  Procedure Typographer.Develop;
  977.   Var
  978.    aFond: Handle;
  979.    aFondRec: FondRecord;
  980.    aStyleMap: StyleMappingTable;
  981.    aStyleList: Array[1..48] Of Str255;
  982.  
  983.    numFonds, currentFond, numFonts: Integer;
  984.  
  985.    aType: ResType;
  986.    aName: Str255;
  987.    aNum: Integer;
  988.    tempFont: FontRecord;
  989.  
  990.   Procedure DoFond;
  991.    Var
  992.     minIndex, maxIndex: Integer;
  993.  
  994.    Procedure CountIndexes;
  995.     Var
  996.      e: Integer;
  997.    Begin
  998.    minIndex := 32767;
  999.    maxIndex := 0;
  1000.    For e := 0 To 47 Do
  1001.     Begin
  1002.     If Ord(aStyleMap.StyleIndex[e]) > maxIndex Then
  1003.      maxIndex := Ord(aStyleMap.StyleIndex[e]);
  1004.     If Ord(aStyleMap.StyleIndex[e]) > 0 Then
  1005.      If Ord(aStyleMap.StyleIndex[e]) < minIndex Then
  1006.       minIndex := Ord(aStyleMap.StyleIndex[e]);
  1007.     End;
  1008.    End;
  1009.  
  1010.    Procedure GetStyles;
  1011.     Var
  1012.      a: Integer;
  1013.      aPtr: Ptr;
  1014.      aStr: Str255;
  1015.    Begin
  1016.    aPtr := Ptr(Longint(@aFond^^) + aFondRec.StyleMapOff + Longint(60));
  1017.  
  1018.    For a := 1 To aStyleMap.NumStyles Do
  1019.     Begin
  1020.     BlockMove(aPtr, @aStyleList[a], Ord(Char(aPtr^)) + 1);
  1021.     aPtr := Ptr(Longint(aPtr) + Length(aStyleList[a]) + 1);
  1022.     End;
  1023.  
  1024.    If (Omit(aStyleList[1], 4, 255) = 'Itc') And (aStyleList[1][4] >= 'A') And
  1025. (aStyleList[1][4] <= 'Z') Then
  1026.     aStyleList[1] := Omit(aStyleList[1], 1, 3);
  1027.    End;
  1028.  
  1029.    Procedure InterpretStyles;
  1030.     Var
  1031.      e, i: Integer;
  1032.      s, t: Str255;
  1033.    Begin
  1034.    For e := 2 To maxIndex Do
  1035.     Begin
  1036.     t := aStyleList[1];
  1037.     For i := 1 To Length(aStyleList[e]) Do
  1038.      Begin
  1039.      s := aStyleList[Ord(aStyleList[e][i])];
  1040.      If (s = 'ExtraBold') Or (s = 'Extra Bold') Then
  1041.       s := 'Extrabold';
  1042.      t := Concat(t, s);
  1043.      End;
  1044.     aStyleList[e] := t;
  1045.     End;
  1046.    End;
  1047.  
  1048.    Function ReplaceTerm (aStr: Str255): Str255;
  1049.    Begin
  1050.    If aStr = 'Cond' Then
  1051.     ReplaceTerm := 'Condensed-'
  1052.  
  1053.    Else If aStr = 'Condensed' Then
  1054.     ReplaceTerm := 'Condensed-'
  1055.  
  1056.    Else If aStr = 'Light' Then
  1057.     ReplaceTerm := 'Light-'
  1058.  
  1059.    Else If aStr = 'Thin' Then
  1060.     ReplaceTerm := 'Thin-'
  1061.  
  1062.    Else If aStr = 'Medium' Then
  1063.     ReplaceTerm := 'Medium-'
  1064.  
  1065.    Else If aStr = 'Heavy' Then
  1066.     ReplaceTerm := 'Heavy-'
  1067.  
  1068.    Else If aStr = 'Heavyface' Then
  1069.     ReplaceTerm := 'Heavyface-'
  1070.  
  1071.    Else If aStr = 'Extrabold' Then
  1072.     ReplaceTerm := 'Extra Bold-'
  1073.  
  1074.    Else If aStr = 'Black' Then
  1075.     ReplaceTerm := 'Black-'
  1076.  
  1077.    Else If aStr = 'Book' Then
  1078.     ReplaceTerm := 'Book-'
  1079.  
  1080.    Else If aStr = 'Ultra' Then
  1081.     ReplaceTerm := 'Ultra-'
  1082.  
  1083.    Else If aStr = 'Obl' Then
  1084.     ReplaceTerm := 'Oblique'
  1085.  
  1086.    Else If aStr = 'Ita' Then
  1087.     ReplaceTerm := 'Italic'
  1088.  
  1089.    Else If aStr = 'Bol' Then
  1090.     ReplaceTerm := 'Bold'
  1091.  
  1092.    Else If aStr = 'Ital' Then
  1093.     ReplaceTerm := 'Italic'
  1094.  
  1095.    Else If aStr = 'Caslon' Then
  1096.     ReplaceTerm := 'Caslon-'
  1097.  
  1098.    Else If aStr = 'Giotto' Then
  1099.     ReplaceTerm := 'Giotto-'
  1100.  
  1101.    Else
  1102.     ReplaceTerm := aStr;
  1103.    End;
  1104.  
  1105.    Procedure RecognizeFace (Var aFace: Str255);
  1106.     Var
  1107.      a: Integer;
  1108.    Begin
  1109.    a := Pos('-', aFace);
  1110.    If a <> 0 Then
  1111.     Begin {Probably contains a valid style}
  1112.     Delete(aFace, a + 1, 255);
  1113.     End
  1114.    Else
  1115.     Begin
  1116.     If aFace = 'Open Face' Then
  1117.      aFace := 'Open Face'
  1118.     Else
  1119.      aFace := '';
  1120.     End;
  1121.    End;
  1122.  
  1123.    Procedure ParseStyles;
  1124.     Var
  1125.      e, i, o, u: Integer;
  1126.      t, term: Str255;
  1127.  
  1128.    Begin
  1129.    For e := minIndex To maxIndex Do
  1130.     Begin
  1131.     u := Length(aStyleList[e]) - 1;
  1132.     t := '';
  1133.     term := Concat('', aStyleList[e][1]);
  1134.     For o := 2 To u Do
  1135.      Begin
  1136.      If (aStyleList[e][o] >= 'A') And (aStyleList[e][o] <= 'Z') Then
  1137.       Begin
  1138.       t := Concat(t, Concat(ReplaceTerm(term), ' '));
  1139.       term := '';
  1140.       End;
  1141.      term := Concat(term, aStyleList[e][o]);
  1142.      End;
  1143.     t := Concat(t, ReplaceTerm(Concat(term, aStyleList[e][o])));
  1144.     aStyleList[e] := t;
  1145.     End;
  1146.    End;
  1147.  
  1148.    Procedure DeriveNames (Var aFamily, aFace, aStyle: Str255);
  1149.     Var
  1150.      o: Integer;
  1151.  
  1152.    Begin
  1153.    o := Pos('-', aFace);
  1154.    If o = 0 Then
  1155.     Begin {Plain name}
  1156.     aFace := 'Regular';
  1157.     aStyle := 'Regular';
  1158.     End
  1159.    Else
  1160.     Begin {Really has a face name}
  1161.     Delete(aFamily, o, 255);
  1162.  
  1163.     If aFace[o + 1] = ' ' Then
  1164.      o := o + 1;
  1165.     Delete(aFace, 1, o);
  1166.     RecognizeFace(aFace);
  1167.  
  1168.     Delete(aStyle, 1, o);
  1169.     o := Length(aFace);
  1170.     If o > 0 Then
  1171.      o := o + 1;
  1172.     If aStyle[o + 1] = ' ' Then
  1173.      o := o + 1;
  1174.     Delete(aStyle, 1, o);
  1175.  
  1176.     aStyle := Strip('-', aStyle);
  1177.     If (aStyle = '') Or (aStyle = ' ') Then
  1178.      aStyle := 'Regular';
  1179.  
  1180.     If (aFace = '') Or (aFace = ' ') Then
  1181.      aFace := 'Regular'
  1182.     Else
  1183.      aFace := Strip('-', aFace);
  1184.     End;
  1185.    End;
  1186.  
  1187.    Function PSStyleIndexToQDStyle (aByte: Byte): Style;
  1188.     Var
  1189.      aStyle: Style;
  1190.    Begin
  1191.    aStyle := [];
  1192.    If BTST(aByte, 0) Then
  1193.     aStyle := aStyle + [bold];
  1194.    If BTST(aByte, 1) Then
  1195.     aStyle := aStyle + [italic];
  1196.    If BTST(aByte, 2) Then
  1197.     aStyle := aStyle + [outline];
  1198.    If BTST(aByte, 3) Then
  1199.     aStyle := aStyle + [shadow];
  1200.    If BTST(aByte, 4) Then
  1201.     aStyle := aStyle + [condense];
  1202.    If BTST(aByte, 5) Then
  1203.     aStyle := aStyle + [extend];
  1204.    PSStyleIndexToQDStyle := aStyle;
  1205.    End;
  1206.  
  1207.    Procedure WriteStyles;
  1208.     Var
  1209.      e, i: Integer;
  1210.      aFamily, aFace, aStyle: Str255;
  1211.  
  1212.    Begin
  1213.    For e := minIndex To maxIndex Do
  1214.     For i := 0 To 47 Do
  1215.      If aStyleMap.StyleIndex[i] = e Then
  1216.       Begin
  1217.       With tempFont Do
  1218.        Begin
  1219.        aFamily := aStyleList[e];
  1220.        aFace := aStyleList[e];
  1221.        aStyle := aStyleList[e];
  1222.        DeriveNames(aFamily, aFace, aStyle);
  1223.  
  1224.        PSFamily := aFamily;
  1225.        PSFace := aFace;
  1226.        PSStyle := aStyle;
  1227.  
  1228.        QDFont := aName;
  1229.        QDFace := aNum;
  1230.        QDStyle := PSStyleIndexToQDStyle(i);
  1231.        End;
  1232.       Insert(tempFont);
  1233.  
  1234.       numFonts := numFonts + 1;
  1235.       i := 47;
  1236.       End;
  1237.    End;
  1238.  
  1239.   Begin
  1240.   aFond := GetIndResource('FOND', currentFond);
  1241.   If Denied(aFond) Then
  1242. {Caution('Could not get a FOND resource.')}
  1243.   Else
  1244.    Begin
  1245.    LockHandle(aFond);
  1246.    GetResInfo(aFond, aNum, aType, aName);
  1247.  
  1248.    BlockMove(Ptr(@aFond^^), @aFondRec, SizeOf(aFondRec));
  1249.  
  1250.    If aFondRec.StyleMapOff > 0 Then
  1251.     Begin
  1252.     BlockMove(Ptr(Longint(@aFond^^) + aFondRec.StyleMapOff), @aStyleMap,
  1253. SizeOf(StyleMappingTable));
  1254.     CountIndexes;
  1255.     GetStyles;
  1256.     InterpretStyles;
  1257.     ParseStyles;
  1258.     WriteStyles;
  1259.     End
  1260.    Else
  1261.     With tempFont Do
  1262.      Begin
  1263.      PSFamily := aName;
  1264.      PSFace := 'Regular';
  1265.      QDFont := aName;
  1266.      QDFace := aNum;
  1267.  
  1268.      PSStyle := 'Regular';
  1269.      QDStyle := [];
  1270.      Insert(tempFont);
  1271.  
  1272.      PSStyle := 'Bold';
  1273.      QDStyle := [bold];
  1274.      Insert(tempFont);
  1275.  
  1276.      PSStyle := 'Bold Italic';
  1277.      QDStyle := [bold] + [italic];
  1278.      Insert(tempFont);
  1279.  
  1280.      PSStyle := 'Italic';
  1281.      QDStyle := [italic];
  1282.      Insert(tempFont);
  1283.      End;
  1284.    UnlockHandle(aFond);
  1285.    ReleaseResource(Handle(aFond));
  1286.    End;
  1287.   End;
  1288.  
  1289.  Begin
  1290.  
  1291.  Expect(CountResources('FONT') + CountResources('NFNT') +
  1292. CountResources('sfnt') + CountResources('FOND'));
  1293.  
  1294.  numFonds := CountResources('FOND');
  1295.  numFonts := 0;
  1296.  
  1297.  For currentFond := 1 To numFonds Do
  1298.   DoFond;
  1299.  
  1300.  Sort;
  1301.  Unique;
  1302.  
  1303.  theTypographer.Expect(theTypographer.Count + 1);
  1304.  Fonds := numFonds;
  1305.  End;
  1306.  
  1307.  Procedure Typographer.Sort;
  1308.  
  1309.   Function GetKeyFromIndex (anIndex: Integer): Str255;
  1310.    Var
  1311.     aFont: FontRecord;
  1312.   Begin
  1313.   If (anIndex >= 0) And (anIndex <= Count) Then
  1314.    Begin
  1315.    aFont := GetEntry(anIndex);
  1316.    GetKeyFromIndex := Concat(Concat(aFont.PSFamily, aFont.PSFace),
  1317. aFont.PSStyle);
  1318.    End
  1319.   Else
  1320.    GetKeyFromIndex := '';
  1321.   End;
  1322.  
  1323.   Function GetKey (aFont: FontRecord): Str255;
  1324.   Begin
  1325.   GetKey := Concat(Concat(aFont.PSFamily, aFont.PSFace), aFont.PSStyle);
  1326.   End;
  1327.  
  1328.   Procedure QuickSort (l, r: Integer);
  1329.    Const
  1330.     QuickSortOverhead = Longint(SizeOf(FontRecord) * 2 + SizeOf(Integer) * 2);
  1331.   Var
  1332.     v, t: FontRecord;
  1333.     i, j: Integer;
  1334.   Begin
  1335.   If r > l Then
  1336.    Begin
  1337.    If StackSpace < QuickSortOverhead Then
  1338.     Danger('The typeface Typographer cannot be sorted.');
  1339.  
  1340.    v := GetEntry(r);
  1341.    i := l - 1;
  1342.    j := r;
  1343.    Repeat
  1344.     Repeat
  1345.      i := i + 1
  1346.     Until (GetKeyFromIndex(i) >= GetKey(v));
  1347.  
  1348.     Repeat
  1349.      j := j - 1
  1350.     Until (GetKeyFromIndex(j) <= GetKey(v));
  1351.  
  1352.     t := GetEntry(i);
  1353.     SetEntry(i, GetEntry(j));
  1354.     SetEntry(j, t);
  1355.    Until j <= i;
  1356.    SetEntry(j, GetEntry(i));
  1357.    SetEntry(i, GetEntry(r));
  1358.    SetEntry(r, t);
  1359.    QuickSort(l, i - 1);
  1360.    QuickSort(i + 1, r);
  1361.    End;
  1362.   End;
  1363.  
  1364.  Begin
  1365. {QuickSort(0, Count);}
  1366.  End;
  1367.  
  1368.  Procedure Typographer.Unique;
  1369.   Var
  1370.    a, e: Integer;
  1371.    this, last: FontRecord;
  1372.  Begin
  1373.  e := 0;
  1374.  last := GetEntry(0);
  1375.  
  1376.  For a := 1 To Count Do
  1377.   Begin
  1378.   this := GetEntry(a);
  1379.   If (this.PSFamily = last.PSFamily) And (this.PSFace = last.PSFace) And
  1380. (this.PSStyle = last.PSStyle) Then
  1381.    e := e + 1
  1382.   Else
  1383.    SetEntry(a - e, this);
  1384.   last := this;
  1385.   End;
  1386.  Count := Count - e;
  1387.  End;
  1388.  
  1389.  Procedure Typographer.Harmony;
  1390.   Var
  1391.    a, e, i, o: Integer;
  1392.    this, next, temp: FontRecord;
  1393.    found, reported: Boolean;
  1394.    lastA, lastB: Str255;
  1395.    timer: Longint;
  1396.  Begin
  1397.  found := false;
  1398.  reported := false;
  1399.  lastA := '';
  1400.  lastB := '';
  1401.  
  1402.  a := Count - 1;
  1403.  For e := 0 To a Do
  1404.   Begin
  1405.   this := GetEntry(e);
  1406.   o := e + 1;
  1407.   For i := o To Count Do
  1408.    Begin
  1409.    next := GetEntry(i);
  1410.    If (next.QDFont <> this.QDFont) Then
  1411.     If (next.QDFace = this.QDFace) Then
  1412.      If (this.QDFont <> lastA) And (next.QDFont <> lastB) Then
  1413.       Begin
  1414.       If found And Not reported Then
  1415.        Begin
  1416.        Stop('Font resource number conflicts have been detected.');
  1417.        Notice(Concat('The fonts ', Concat(Concat(Concat(lastA, ' and '),
  1418. lastB), ' have the same font resource numbers.')));
  1419.        reported := true;
  1420.        End;
  1421.       If found Then
  1422.        Notice(Concat('The fonts ', Concat(Concat(Concat(this.QDFont, ' and '),
  1423. next.QDFont), ' have the same font resource numbers.')));
  1424.       found := true;
  1425.       lastA := this.QDFont;
  1426.       lastB := next.QDFont;
  1427.       End;
  1428.    End;
  1429.   End;
  1430.  
  1431.  If found And Not reported Then
  1432.   Begin
  1433.   Stop('A font resource number conflict has been detected.');
  1434.   Notice(Concat('The fonts ', Concat(Concat(Concat(lastA, ' and '), lastB), '
  1435. have the same font resource numbers.')));
  1436.   End;
  1437.  
  1438.  End;
  1439.  
  1440.  Procedure Typographer.Destruct;
  1441.  Begin
  1442.  Dispose;
  1443.  End;
  1444.  
  1445. - ------- Cut here
  1446.  
  1447.  
  1448. Theus (orpheus@reed.edu)
  1449.  
  1450. +++++++++++++++++++++++++++
  1451.  
  1452. From: ewylie@ocf.berkeley.edu (Elizabeth Wylie)
  1453. Date: 12 Jun 1992 05:06:28 GMT
  1454. Organization: U.C. Berkeley Open Computing Facility
  1455.  
  1456. Thanks to all who responded.  I was not able to find the adobe information on sumex-aim (has it been removed) but I enquired at adobe and they are sending me their TechNote #2 and a disk.                                           
  1457.  
  1458. Several people made the assumption that 'there must be a better way of finding out what you need to know'.  I suppose I wasn't clear enough.  I need to know whether 17 point Helvetica (for instance) will be drawn as a scaled bitmap or if ATM will take over and draw it as PostScript.  The only clean way to do this is to ask ATM via it's backdoor routines.
  1459.  
  1460. - -Elizabeth
  1461. .
  1462. 
  1463. 
  1464.  
  1465.  
  1466. ---------------------------
  1467.  
  1468. End of C.S.M.P. Digest
  1469. **********************
  1470.